/**
 * 
 */
package com.xpec.c4.game.login.async2;

import java.math.BigDecimal;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ms.player.Player;
import com.ms.service.error.ErrorCode;
import com.ms.service.module.account.db.AccountDAO;
import com.ms.service.module.account.db.CooperatorInfoField;
import com.xpec.c4.db.basic.BasicLogDAO;
import com.xpec.c4.db.dao.PlayerDAO;
import com.xpec.c4.game.common.Helper;
import com.xpec.c4.game.datamanager.ResultNo;
import com.xpec.c4.game.datamanager.agent.money.MoneyChangeWay;
import com.xpec.c4.game.login.LoginModule;
import com.xpec.c4.game.login.LoginSender;
import com.xpec.c4.game.login.async.CharacterLoginRequestGetPlayer;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.game.utility.GUIDFactory;
import com.xpec.c4.game.utility.GUIDType;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.service.module.datacenter.player.UpdateH5PlayerMoneyToDbAsync;
import com.xpec.c4.service.module.datacenter.player.db.TmpCashChangeWay;

/**
 * @author TW15010
 *
 */
public class CharacterLoginGetPlayerAsync extends DoAfterLoadPlayerAsync {
	/** log4j object */
	private static final Log log = LogFactory.getLog(CharacterLoginGetPlayerAsync.class);

	/**
	 * 登入時向 DC 讀取角色資料的 request
	 */
	CharacterLoginRequestGetPlayer data;

	@Override
	public void execute() throws Exception {
		// TODO kevin jb verify
		switch (getResultCode()) {
		case ResultNo.OK: {
			// 把sessionID填入Player以供登入進大廳之前的流程參考2017/05/31
			Player player = getLoadPlayer();
			player.setSessionID(data.sessionID);
			data.player = player;
			data.result = true;

			// 從暫存錢包把錢轉到 player 上
			boolean res = autoTakeTmpCash(player);
			if (!res) {
				LoginSender.sendAccountMessage(data.sessionID, ErrorCode.DB_OPERATION_FAIL);
				return;
			}

			((LoginModule) getCurrentModuleServer()).characterLoginRequestGetPlayerCallback(data);
			break;
		}

		case ResultNo.ACCESS_DENY:
			log.info("Access deny  id: " + getLoadPlayerId());
			break;

		case ResultNo.FAILED:
			log.info("Query failed  id: " + getLoadPlayerId());
			break;

		case ResultNo.DATA_NOT_FOUND:
			log.info("Data not found id: " + getLoadPlayerId());
			break;

		case ResultNo.DB_OPERATION_FAILED:
			log.info("DB operation failed id: " + getLoadPlayerId());
			break;
		}
	}
	
	/**
	 * 從暫存錢包把錢轉到 player 上
	 * 
	 * @param player
	 * @param sessionId
	 * @return
	 */
	private boolean autoTakeTmpCash(Player player) {
		if (player == null) {
			return false;
		}

		// 鎖定資料
		if (!AccountDAO.dataLock(player.getCooperatorAccountId())) {
			// 鎖定資料失敗就跳過
			return false;
		}
		
		// 取得帳號資訊
		Map<String, String> coopInfoMap = AccountDAO.getCoopInfo(player.getCooperatorAccountId());

		// 取出目前暫存錢包的金額
		String curTmpCashStr = coopInfoMap.get(CooperatorInfoField.TMP_CASH);

		BigDecimal curTmpCash = BigDecimal.ZERO;
		if (GameUtility.isHaveString(curTmpCashStr)) {
			curTmpCash = new BigDecimal(curTmpCashStr);
		}

		// 暫存錢包沒錢, 當作是成功
		if (Helper.isEqual(curTmpCash, BigDecimal.ZERO)) {
			AccountDAO.dataUnlock(player.getCooperatorAccountId());
			return true;
		}

		// 要取出的金額
		BigDecimal takeCash = curTmpCash;

		// 玩家身上的金額
		BigDecimal curPlayerGold = player.getGoldCoin();

		// 暫存扣掉
		BigDecimal newTmpCash = Helper.sub(curTmpCash, takeCash);

		// 加到玩家身上
		BigDecimal newPlayerGold = Helper.add(curPlayerGold, takeCash);

		// 儲存暫存錢包到 redis
		boolean res = AccountDAO.saveCoopInfoField(player.getCooperatorAccountId(), CooperatorInfoField.TMP_CASH,
				newTmpCash.toString());
		if (!res) {
			if (log.isErrorEnabled()) {
				GameUtility.failErrorLog(log, "save tmp cash fail. newTmpCash=" + newTmpCash + " playerGold="
						+ newPlayerGold, GameUtility.getCurMethodName(), player.getGuid(),
						player.getCooperatorAccountId(), player.getSessionID());
			}
			AccountDAO.dataUnlock(player.getCooperatorAccountId());
			return false;
		}

		// 儲存到玩家身上
		player.setgoldCoin(newPlayerGold);

		// player 寫回 redis
		res = PlayerDAO.savePlayerToRedis(player);
		if (!res) {
			if (log.isErrorEnabled()) {
				GameUtility.failErrorLog(log, "save player fail. newTmpCash=" + newTmpCash + " playerGold="
						+ newPlayerGold, GameUtility.getCurMethodName(), player.getGuid(),
						player.getCooperatorAccountId(), player.getSessionID());
			}
			AccountDAO.dataUnlock(player.getCooperatorAccountId());
			return false;
		}

		// 解鎖
		AccountDAO.dataUnlock(player.getCooperatorAccountId());


		// TODO kevin save tmp cash log

		// 寫暫存錢包 log
		GUID orderId = GUIDFactory.createUUID(GUIDType.TYPE_RECHARGE);
		TmpCashChangeWay tmpCashChangeWay = TmpCashChangeWay.SUB_TO_PLAYER_ON_LOGIN;

		BasicLogDAO.saveTmpCashChangeLog(
				orderId,
				coopInfoMap.get(CooperatorInfoField.ACCOUNT_ID),
				coopInfoMap.get(CooperatorInfoField.PLAYER_ID),
				coopInfoMap.get(CooperatorInfoField.OPEN_ID),
				coopInfoMap.get(CooperatorInfoField.PLAYER_NAME),
				getCurrentModuleServer().getModuleName(),
				getCurrentModuleServer().getModuleName(),
				player.getAgentDataInstance().getCoinType(),
				takeCash,
				curTmpCash,
				newTmpCash,
				takeCash,
				curPlayerGold,
				newPlayerGold,
				tmpCashChangeWay,
				coopInfoMap.get(CooperatorInfoField.VENDER_ID),
				coopInfoMap.get(CooperatorInfoField.SUB_VENDER_ID),
				getCurrentModuleServer()
		);

		// 寫 money change log
		BasicLogDAO.savePlayerMoneyChangeLog(
				player, 
				getCurrentModuleServer().getModuleName(), 
				getCurrentModuleServer().getModuleName(), 
				getCurrentModuleServer().getModuleName(), 
				getCurrentModuleServer().getModuleName(), 
				MoneyChangeWay.ADD_H5_FROM_TMP_CASH_ON_AUTO_REFRESH, 
				orderId, 
				takeCash, 
				curPlayerGold, 
				newPlayerGold, 
				getCurrentModuleServer()
		);
		
		// 錢更新回 db
		UpdateH5PlayerMoneyToDbAsync async =  new UpdateH5PlayerMoneyToDbAsync();
		async.initial(player.getGuid(), newPlayerGold, newTmpCash);
		
		getCurrentModuleServer().addAsyncCommand(async);

		return true;
	}

	public CharacterLoginRequestGetPlayer getData() {
		return data;
	}

	public void setData(CharacterLoginRequestGetPlayer data) {
		this.data = data;
	}
}
